# pragma once

# include "cpp_tools_Headers.h"

namespace cpp_tools
{
    class udpSocket
    {
    public:
        int sockfd;
        int sockFlag;

        explicit udpSocket(bool nonBlock = 0)
        {
            sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (sockfd < 0)
            {
                perror("udpSocket--warning: socket init failed\n");
            }

            if (nonBlock)
            {
                // 非阻塞模式
                sockFlag = fcntl(sockfd, F_GETFL, 0);
                fcntl(sockfd, F_SETFL, sockFlag | O_NONBLOCK);
            }
        };

        ~udpSocket()
        {
            close(sockfd);
        };

        // 禁用拷贝构造和赋值操作
        udpSocket(const udpSocket& other) = delete;
        udpSocket& operator=(const udpSocket& other) = delete;
        
        // 允许移动构造和赋值操作
        udpSocket(udpSocket&& other) noexcept : sockfd(other.sockfd), sockFlag(other.sockFlag)
        {
            other.sockfd = -1;
        }
        
        udpSocket& operator=(udpSocket&& other) noexcept
        {
            if (this != &other)
            {
                sockfd = other.sockfd;
                sockFlag = other.sockFlag;
                other.sockfd = -1;
            }
            return *this;
        }
    };



    template <typename T>
    class udpVecReceiver
    {
    protected:
        sockaddr_in addr_self;
        sockaddr_in addr_others;
        socklen_t addr_len;

        T* buffer;

        udpSocket sock_; // 假设 udpSocket 是一个有效的类

        const int size;
        Eigen::VectorX<T> data; // 使用模板类型 T

        void init(const int PORT)
        {
            // 配置服务地址
            memset(&addr_self, 0, sizeof(addr_self));
            addr_self.sin_family = AF_INET;
            addr_self.sin_addr.s_addr = INADDR_ANY;
            addr_self.sin_port = htons(PORT);

            // 绑定
            int flag = bind(sock_.sockfd, (const sockaddr*)(&addr_self), sizeof(addr_self));
            if (flag < 0)
            {
                perror("udpVecReceiver: bind failed\n");
            }

            // 初始化
            addr_len = sizeof(addr_others);
            buffer = new T[size];
            std::cout << "udpVecReceiver: bound at port: " << PORT << ", with buffer size: " << size << std::endl;
        }

    public:
        udpVecReceiver(int dataSize, const int PORT, const udpSocket& sock)
            : size(dataSize), sock_(std::move(sock)), data(dataSize)
        {
            init(PORT);
        }

        udpVecReceiver(int dataSize, const int PORT, const bool nonBlock)
            : size(dataSize), sock_(nonBlock), data(dataSize)
        {
            init(PORT);
        }

        ~udpVecReceiver()
        {
            delete[] buffer;
        }

        /// @brief int receive()
        /// @return 
        ///      -2: 完全没有数据；
        ///      -1: 小于给定数据长度；
        ///       0: 完整的数据长度；
        int receive()
        {
            int n = recvfrom(sock_.sockfd, buffer, sizeof(T) * size, 0, (sockaddr*)&addr_others, &addr_len) / sizeof(T);
            if (n <= 0)
            {
                return -2;
            }
            else if (n < size)
            {
                data.topRows(n) = Eigen::VectorX<T>::Map(buffer,n);
                data.bottomRows(size - n) = Eigen::VectorX<T>::Constant(size - n,std::numeric_limits<T>::quiet_NaN());

                return -1;
            }
            else
            {
                data = Eigen::VectorX<T>::Map(buffer,n);
            }

            return 0;
        }

        Eigen::VectorX<T> & get()
        {
            return data;
        }
    };
    


    template <typename T>
    class udpVecSender
    {
    protected:
        sockaddr_in addr_self;
        sockaddr_in addr_goal;

        udpSocket sock_;

        void init(const std::string IP, const int PORT)
        {
            // 配置服务地址
            memset(&addr_goal, 0, sizeof(addr_goal));
            addr_goal.sin_family = AF_INET;
            addr_goal.sin_port = htons(PORT);

            // 绑定
            if (inet_pton(AF_INET, IP.c_str(), &addr_goal.sin_addr) <= 0)
            {
                std::cerr<<"udpVecSender: Unsupported IP"<<std::endl;
            }
        }

    public:
        const std::string IP_;

        udpVecSender(const std::string IP, const int PORT, const udpSocket &sock)
            : IP_(IP), sock_(std::move(sock))
        {
            init(IP, PORT);
        };

        udpVecSender(const std::string IP, const int PORT, const bool nonblock)
            : IP_(IP), sock_(nonblock)
        {
            init(IP, PORT);
        };

        ~udpVecSender(){};

        void send(const Eigen::VectorX<T> & data)
        {
            sendto(sock_.sockfd, data.data(), data.size()*sizeof(T), 0, (sockaddr*)&addr_goal, sizeof(addr_goal));
        }
    };



    template <typename T>
    class udpVecServer
    {
    protected:
        sockaddr_in addr_self;
        sockaddr_in addr_others;
        sockaddr_in addr_goal;
        socklen_t addr_len;

        bool have_goal = false;

        T* buffer;

        udpSocket sock_; // 假设 udpSocket 是一个有效的类

        const int size;
        Eigen::VectorX<T> data; // 使用模板类型 T

        void init(const int PORT)
        {
            // 配置服务地址
            memset(&addr_self, 0, sizeof(addr_self));
            addr_self.sin_family = AF_INET;
            addr_self.sin_addr.s_addr = INADDR_ANY;
            addr_self.sin_port = htons(PORT);

            // 绑定
            int flag = bind(sock_.sockfd, (const sockaddr*)(&addr_self), sizeof(addr_self));
            if (flag < 0)
            {
                perror("udpVecServer: bind failed\n");
            }

            // 初始化
            addr_len = sizeof(addr_others);
            buffer = new T[size];
            std::cout << "udpVecServer: bound at port: " << PORT << ", with buffer size: " << size << std::endl;
        }

    public:
        udpVecServer(int dataSize, const int PORT, const udpSocket& sock)
            : size(dataSize), sock_(std::move(sock)), data(dataSize)
        {
            init(PORT);
        }

        udpVecServer(int dataSize, const int PORT, const bool nonBlock)
            : size(dataSize), sock_(nonBlock), data(dataSize)
        {
            init(PORT);
        }

        ~udpVecServer()
        {
            delete[] buffer;
        }

        /// @brief int receive()
        /// @return 
        ///      -2: 完全没有数据；
        ///      -1: 小于给定数据长度；
        ///       0: 完整的数据长度；
        int receive()
        {
            int n = recvfrom(sock_.sockfd, buffer, sizeof(T) * size, 0, (sockaddr*)&addr_others, &addr_len) / sizeof(T);
            if (n <= 0)
            {
                return -2;
            }
            else if (n < size)
            {
                data.topRows(n) = Eigen::VectorX<T>::Map(buffer,n);
                data.bottomRows(size - n) = Eigen::VectorX<T>::Constant(size - n,std::numeric_limits<T>::quiet_NaN());

                return -1;
            }
            else
            {
                data = Eigen::VectorX<T>::Map(buffer,n);
            }

            return 0;
        }

        int setGoal(const std::string IP, const int PORT)
        {
            // 配置地址
            memset(&addr_goal, 0, sizeof(addr_goal));
            addr_goal.sin_family = AF_INET;
            addr_goal.sin_port = htons(PORT);

            // 绑定
            int flag = inet_pton(AF_INET, IP.c_str(), &addr_goal.sin_addr);
            if (flag <= 0)
            {
                std::cerr<<"udpVecServer: Unsupported IP"<<std::endl;
            }
            else
            {
                have_goal = true;
            }

            return flag;
        }

        void send(const Eigen::VectorX<T> & data)
        {
            if (!have_goal)
            {
                std::runtime_error("udpVecServer: 未设置发送目标");
            }
            
            sendto(sock_.sockfd, data.data(), data.size()*sizeof(T), 0, (sockaddr*)&addr_goal, sizeof(addr_goal));
        }

        /// @brief 向发送方回传数据
        /// @param response 要回传的Eigen向量数据
        /// @return 成功发送的字节数，失败返回-1
        ssize_t sendBack(const Eigen::VectorX<T>& response)
        {
            // 检查socket是否有效
            if (sock_.sockfd < 0)
            {
                std::cerr << "udpVecServer: invalid socket" << std::endl;
                return -1;
            }

            // 发送数据回给最后一个发送方
            ssize_t bytes_sent = sendto(
                sock_.sockfd,
                response.data(),
                response.size() * sizeof(T),
                0,
                (const sockaddr*)&addr_others,
                addr_len
            );

            // std::cout << "sendback to "
            // << inet_ntoa(addr_others.sin_addr) << ':'
            // << ntohs(addr_others.sin_port) << std::endl;

            if (bytes_sent < 0)
            {
                perror("udpVecServer: sendback failed");
                return -1;
            }

            return bytes_sent;
        }

        Eigen::VectorX<T> & get()
        {
            return data;
        }
    };
} // namespace cpp_tools
